/*
 * This file is part of ddesktop: remote desktop system for iPad 
 *
 * Copyright (C) 2010 Kazuhiro Satoh
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. if not, see <http://www.gnu.org/licenses/>.
 */


#include "stdafx.h"
#include "DesktopCapture.h"

#pragma unmanaged

#include <windows.h>

#define CAPTURE_BYTES_PER_PIXEL  3

namespace DDesktopServer{

	DesktopCapture::DesktopCapture()
	{
		m_capture_bmp_dc = 0;
		m_capture_bmp_old = 0;
		m_capture_bmp = 0;
		m_desktop_dc = 0;
	}


	DesktopCapture::~DesktopCapture()
	{
		if(m_capture_bmp_dc){
			if(m_capture_bmp_old){
				SelectObject(m_capture_bmp_dc, m_capture_bmp_old);
			}
			if(m_capture_bmp){
				DeleteObject(m_capture_bmp);
			}
			DeleteDC(m_capture_bmp_dc);
		}
		if(m_desktop_dc){
			ReleaseDC(NULL, m_desktop_dc);
		}
	}


	bool DesktopCapture::Init(int canvas_width, int canvas_height)
	{
		m_canvas_width = canvas_width;
		m_canvas_height = canvas_height;
		m_bytes_per_pixel = CAPTURE_BYTES_PER_PIXEL;

		{ // create bmp
			BITMAPINFO  bi;

			::ZeroMemory( &bi, sizeof(bi) );
			bi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
			bi.bmiHeader.biBitCount    = m_bytes_per_pixel * 8;
			bi.bmiHeader.biPlanes      = 1;
			bi.bmiHeader.biWidth       = canvas_width;
			bi.bmiHeader.biHeight      = canvas_height;
			bi.bmiHeader.biSizeImage   = canvas_width * canvas_height * m_bytes_per_pixel;
			bi.bmiHeader.biCompression = BI_RGB;
			m_capture_bmp = ::CreateDIBSection( NULL, &bi, DIB_RGB_COLORS, (void **)(&m_capture_bmp_address), NULL, 0);
		}

		{ // prepare dc
			m_desktop_dc = ::GetDC(NULL);
			m_capture_bmp_dc = ::CreateCompatibleDC(m_desktop_dc);
			m_capture_bmp_old = (HBITMAP)::SelectObject(m_capture_bmp_dc, m_capture_bmp);
		}

		return true;
	}


	bool DesktopCapture::Capture(int x, int y, int width, int height)
	{
		m_capture_bmp_x = x;
		m_capture_bmp_y = y;
		m_capture_bmp_width = width;
		m_capture_bmp_height = height;

		BitBlt(
			m_capture_bmp_dc,		// dest
			0,						// dest x
			0,						// dest y
			width,					// dest width
			height,					// dest height
			m_desktop_dc,			// src
			x,						// src x
			y,						// src y
			SRCCOPY
			);

		{ // draw mouse cursor
			CURSORINFO cursor_info;
			ICONINFO icon_info;
			cursor_info.cbSize = sizeof(CURSORINFO);
			::GetCursorInfo(&cursor_info);
			::GetIconInfo(cursor_info.hCursor, &icon_info);
			::DrawIcon(
				m_capture_bmp_dc,
				cursor_info.ptScreenPos.x - icon_info.xHotspot - x,
				cursor_info.ptScreenPos.y - icon_info.yHotspot - y,
				cursor_info.hCursor
			);
			::DeleteObject(icon_info.hbmColor);
			::DeleteObject(icon_info.hbmMask);
		}

		return true;
	}


	HBITMAP DesktopCapture::GetCaptureBmp(void) const
	{
		return m_capture_bmp;
	}

	HDC DesktopCapture::GetCaptureBmpDC(void) const
	{
		return m_capture_bmp_dc;
	}

	LPVOID DesktopCapture::GetCaptureBmpAddress(void)
	{
		return m_capture_bmp_address;
	}

	int DesktopCapture::GetCaptureBmpSize(void) const
	{
		return m_capture_bmp_width * m_capture_bmp_height * m_bytes_per_pixel;
	}

	int DesktopCapture::GetCaptureBmpWidth(void) const
	{
		return m_capture_bmp_width;
	}

	int DesktopCapture::GetCaptureBmpHeight(void) const
	{
		return m_capture_bmp_height;
	}

	int DesktopCapture::GetCaptureBmpX(void) const
	{
		return m_capture_bmp_x;
	}

	int DesktopCapture::GetCaptureBmpY(void) const
	{
		return m_capture_bmp_y;
	}

	int DesktopCapture::GetCanvasWidth(void) const
	{
		return m_canvas_width;
	}

	int DesktopCapture::GetCanvasHeight(void) const
	{
		return m_canvas_height;
	}
}